﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using Pixysoft.Framework.Noebe.Orm.Core;
using Pixysoft.Framework.Reflection;
using Pixysoft.Framework.Verifications;
using System.Data;

namespace Pixysoft.Framework.Noebe.Orm.Controller
{
    static class ConversionController
    {
        /// <summary>
        /// 对象转主键
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Int64 ObjectToPrimaryKey(object value)
        {
            ObjectProxy proxy = ObjectToProxy(value);

            return ProxyToPrimaryKey(proxy);
        }

        /// <summary>
        /// 对象代理转主键
        /// </summary>
        /// <returns></returns>
        public static Int64 ProxyToPrimaryKey(ObjectProxy proxy)
        {
            if (proxy == null)
                return StringHelper.GetNullPrimaryKey();
            else
                return proxy.SidValue;
        }

        /// <summary>
        /// 对象集合转主键
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static List<Int64> ObjectListToPrimaryKeyList(IList value)
        {
            List<ObjectProxy> proxys = ObjectListToProxyList(value);

            return ProxyListToPrimaryKeyList(proxys);
        }

        private static List<Int64> ProxyListToPrimaryKeyList(List<ObjectProxy> objlist)
        {
            return ProxyArrayToPrimaryKeyList(objlist.ToArray());
        }

        private static List<Int64> ProxyArrayToPrimaryKeyList(params ObjectProxy[] objs)
        {
            List<Int64> list = new List<long>();

            foreach (ObjectProxy proxy in objs)
            {
                list.Add(ProxyToPrimaryKey(proxy));
            }

            return list;
        }


        public static object ProxyToObject(Type type, ObjectProxy proxy)
        {
            DynamicOrmProxy dynamicProxy = new DynamicOrmProxy(type, proxy);
            return dynamicProxy.GetTransparentProxy();
        }

        public static ObjectProxy ObjectToProxy(object value)
        {
            DynamicOrmProxy dproxy = ObjectToDynamicOrmProxy(value);

            ObjectProxy _proxy = dproxy.GetProxy();

            return _proxy;
        }

        private static DynamicOrmProxy ObjectToDynamicOrmProxy(object value)
        {
            if (value == null)
                return null;

            DynamicTransparentProxyBase tproxy = value as DynamicTransparentProxyBase;

            if (tproxy == null)
                throw Exceptions.UnexpectedResultException("unsupport transparent dynamic proxy for " + value);

            DynamicOrmProxy dproxy = tproxy.GetProxy() as DynamicOrmProxy;

            if (dproxy == null)
                throw Exceptions.UnexpectedResultException("access dynamic orm proxy from transparent proxy fail, for " + value);

            return dproxy;
        }


        public static List<ObjectProxy> ObjectListToProxyList(IList value)
        {
            List<ObjectProxy> proxyList = new List<ObjectProxy>();

            foreach (object obj in value)
            {
                if (obj == null)
                    continue;

                ObjectProxy proxy = ObjectToProxy(obj);

                if (proxy == null)
                    continue;

                proxyList.Add(proxy);
            }

            return proxyList;
        }

        public static IList ProxyListToObjectList(Type type, List<ObjectProxy> objs)
        {
            IList list = Activator.CreateInstance(type) as IList;

            if (objs.Count == 0)
                return list;

            Type[] argTypes = type.GetGenericArguments();

            foreach (ObjectProxy proxy in objs)
            {
                list.Add(ProxyToObject(argTypes[0], proxy));
            }

            return list;
        }

        public static IList ProxyListToCollection(Type type, List<ObjectProxy> objs)
        {
            if (objs.Count == 0)
                return null;

            ArrayList list = new ArrayList();

            Type elementType = type.GetElementType();

            int counter = 0;

            foreach (ObjectProxy proxy in objs)
            {
                list.Add(ProxyToObject(elementType, proxy));

                counter++;
            }

            return list.ToArray(elementType);
        }



        /// <summary>
        /// 根据要求把值转化成为用户值
        /// </summary>
        /// <param name="method"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static object ObjectToValue(Type type, object value)
        {
            if (value == null || value == DBNull.Value)
                return Pixysoft.Tools.ParserHelper.GetNullValue(type);

            object outvalue;

            if (Pixysoft.Tools.ParserHelper.TryParse(type, value, out outvalue, null))
                return outvalue;

            return Pixysoft.Tools.ParserHelper.GetNullValue(type);
        }


        public static object StringToEnum(Type type, string value)
        {
            return Enum.Parse(type, value);
        }

        public static object StringToEnum(Type type)
        {
            return Enum.ToObject(type, 0);
        }


        public static IList IListToValueList(Type type, IList values)
        {
            Type argType = type.GetGenericArguments()[0];

            switch (EnumCoder.ToEnum<DotNetDataType>(argType.Name))
            {
                case DotNetDataType.Boolean:
                    {
                        return IListToValueList<Boolean>(values);
                    }

                case DotNetDataType.Byte:
                    {
                        return IListToValueList<Byte>(values);
                    }

                case DotNetDataType.Char:
                    {
                        return IListToValueList<char>(values);
                    }

                case DotNetDataType.DateTime:
                    {
                        return IListToValueList<DateTime>(values);
                    }

                case DotNetDataType.Decimal:
                    {
                        return IListToValueList<Decimal>(values);
                    }

                case DotNetDataType.Double:
                    {
                        return IListToValueList<Double>(values);

                    }

                case DotNetDataType.Int32:
                    {
                        return IListToValueList<Int32>(values);

                    }

                case DotNetDataType.Int64:
                    {
                        return IListToValueList<Int64>(values);
                    }

                case DotNetDataType.Single:
                    {
                        return IListToValueList<Single>(values);
                    }

                default:
                case DotNetDataType.String:
                    {
                        return IListToValueList<string>(values);
                    }
            }
        }

        private static List<T> IListToValueList<T>(IList values)
        {
            List<T> list = new List<T>();

            foreach (object value in values)
            {
                if (value == null)
                    list.Add(default(T));
                else
                    list.Add((T)value);
            }

            return list;
        }


        public static IList IListToValueCollection(Type type, IList values)
        {
            switch (EnumCoder.ToEnum<DotNetDataType>(type.GetElementType().Name))
            {
                case DotNetDataType.Boolean:
                    {
                        return IListToValueCollection<Boolean>(values);
                    }

                case DotNetDataType.Byte:
                    {
                        return IListToValueCollection<Byte>(values);
                    }

                case DotNetDataType.Char:
                    {
                        return IListToValueCollection<char>(values);
                    }

                case DotNetDataType.DateTime:
                    {
                        return IListToValueCollection<DateTime>(values);
                    }

                case DotNetDataType.Decimal:
                    {
                        return IListToValueCollection<Decimal>(values);
                    }

                case DotNetDataType.Double:
                    {
                        return IListToValueCollection<Double>(values);

                    }

                case DotNetDataType.Int32:
                    {
                        return IListToValueCollection<Int32>(values);

                    }

                case DotNetDataType.Int64:
                    {
                        return IListToValueCollection<Int64>(values);
                    }

                case DotNetDataType.Single:
                    {
                        return IListToValueCollection<Single>(values);
                    }

                default:
                case DotNetDataType.String:
                    {
                        return IListToValueCollection<string>(values);
                    }
            }
        }

        private static IList IListToValueCollection<T>(IList values)
        {
            IList list = new T[values.Count];

            int counter = 0;

            foreach (object value in values)
            {
                if (value == null)
                    list[counter] = default(T);
                else
                    list[counter] = (T)value;

                counter++;
            }

            return list;
        }
    }
}
